﻿using Abp;
using Abp.Application.Services.Dto;
using Abp.Runtime.Session;
using Abp.Timing;
using Abp.WebApi.Client;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using RMM.FrameWork;
using RMM.Models;
using RMM.UserAppService;
using RMM.Users.Dtos;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Configuration;
using System.Web.Mvc;

namespace RMM.Controllers
{
    public class WeixinController : Controller
    {
        private readonly IAbpWebApiClient _abpWebApiClient;
        private readonly IAbpSession abpSession;
        private readonly IUserAppService _userAppService;
#if !DEBUG
        private string baseUrl = "https://uapi.rmmll.com";
#else
        private string baseUrl = "http://localhost:61755";
#endif
        private string webapiUrl = "/api/services/app/User/GetUsers";
        private string oAuthTokenUrl = "/oauth/token";
        private string appId = WebConfigurationManager.AppSettings["AppId"]?.ToString();
        private string appSecret = WebConfigurationManager.AppSettings["AppSecret"]?.ToString();

        public WeixinController(IUserAppService userAppService)
        {
            _abpWebApiClient = new AbpWebApiClient();
            abpSession = NullAbpSession.Instance;
            _userAppService = userAppService;
        }

        // GET: Wexin
        public ActionResult Index()
        {
            return View();
        }


#region OAuth2认证方式
        [HttpPost]
        public async Task<string> Register(RegisterInputDto dto)
        {
            var openId = await _userAppService.Register(dto);
            return await GetToken(openId);
        }


        public async Task<string> GetOAuth2Token(string code , string pwd = "1")
        {

            var url = "https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type=authorization_code";
            url = string.Format(url, appId, appSecret, code);
            var loginDto = await CommonHelper.GetAsync<WxLoginDto>(url);
            if (CommonHelper.Check(loginDto.errcode))
            {
                return loginDto.errmsg;
            }

            return await GetToken(loginDto.openid);
        }

        public async Task<string> GetToken(string openId)
        {
            Uri uri = new Uri(baseUrl + oAuthTokenUrl);
            var handler = new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.None };

            using (var client = new HttpClient(handler))
            {
                client.BaseAddress = uri;
                client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));

                var content = new FormUrlEncodedContent(new Dictionary<string, string>()
                {
                    {"grant_type", "password"},
                    {"username", openId },
                    {"password", "RMM" },
                    {"client_id", "app" },
                    {"client_secret", "app"},
                });

                HttpResponseMessage result = new HttpResponseMessage();
                try
                {
                    result = await client.PostAsync(uri, content);
                }
                catch (Exception ex)
                {

                }
                result.EnsureSuccessStatusCode();
                string tokenResult = await result.Content.ReadAsStringAsync();

                var tokenObj = (JObject)JsonConvert.DeserializeObject(tokenResult);
                string token = tokenObj["access_token"].ToString();
                string refreshToken = tokenObj["refresh_token"].ToString();
                long expires = Convert.ToInt64(tokenObj["expires_in"]);

                this.Response.SetCookie(new HttpCookie("access_token", token));
                this.Response.SetCookie(new HttpCookie("refresh_token", refreshToken));
                this.Response.Cookies["access_token"].Expires = Clock.Now.AddSeconds(expires);

                return tokenResult;
            }
        }

        public async Task<string> GetOAuth2TokenByRefreshToken(string refreshToken)
        {
            Uri uri = new Uri(baseUrl + oAuthTokenUrl);
            var handler = new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.None, UseCookies = true };

            using (var client = new HttpClient(handler))
            {
                client.BaseAddress = uri;
                client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));

                var content = new FormUrlEncodedContent(new Dictionary<string, string>()
                {
                    {"grant_type", "refresh_token"},
                    {"refresh_token", refreshToken},
                    {"client_id", "app" },
                    {"client_secret", "app"},
                });

                //获取token保存到cookie，并设置token的过期日期                    
                var result = await client.PostAsync(uri, content);
                result.EnsureSuccessStatusCode();
                string tokenResult = await result.Content.ReadAsStringAsync();

                var tokenObj = (JObject)JsonConvert.DeserializeObject(tokenResult);
                string token = tokenObj["access_token"].ToString();
                string newRefreshToken = tokenObj["refresh_token"].ToString();
                long expires = Convert.ToInt64(tokenObj["expires_in"]);

                this.Response.SetCookie(new HttpCookie("access_token", token));
                this.Response.SetCookie(new HttpCookie("refresh_token", newRefreshToken));
                this.Response.Cookies["access_token"].Expires = Clock.Now.AddSeconds(expires);

                return tokenResult;
            }
        }

        public async Task<ActionResult> SendRequestWithOAuth2Token()
        {
            var token = Request.Cookies["access_token"]?.Value;
            if (token == null)
            {
                string refreshToken = Request.Cookies["refresh_token"].Value;
                var tokenResult = await GetOAuth2TokenByRefreshToken(refreshToken);
                var tokenObj = (JObject)JsonConvert.DeserializeObject(tokenResult);
                token = tokenObj["access_token"].ToString();
            }

            _abpWebApiClient.RequestHeaders.Add(new NameValue("Authorization", "Bearer " + token));

            return await GetUserList(baseUrl + webapiUrl);
        }

#endregion

        private async Task<PartialViewResult> GetUserList(string url)
        {
            try
            {
                var c = abpSession.UserId;
                var users = await _abpWebApiClient.PostAsync<ListResultDto<UserListDto>>(url);

                return PartialView("_UserListPartial", users.Items);
            }
            catch (Exception e)
            {
                ViewBag.ErrorMessage = e.Message;
            }

            return null;
        }

    }
}
